"""
Case Type   : 进程故障
Case Name   : 数据库运行时，主机注入故障进程D 状态
Create At   : 2021/8/26
Owner       : li-xin12345
Description :
    1.核对数据库状态
    2.注入进程D 状态故障
    3.核对数据库状态
    4.恢复环境
    5.执行tpcc
    6.核对一致性
    7.恢复环境
Expect      :
    1.Normal
    2.成功
    3.Unavailable
    4.成功
    5.成功
    6.一致
    7.成功
History     :
"""
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node, macro


class ReliabilityProcess(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.primary_sh = CommonSH(self.nodes[0])
        self.primary_root_node = Node(node="PrimaryRoot")
        self.primary_user_node = Node(node="PrimaryDbUser")
        self.constant = Constant()
        self.com = Common()

        self.log.info("Opengauss_Reliability_Process_Case010:开始执行")
        self.port = Node("PrimaryDbUser").db_port

        self.log.info("查询数据库进程号")
        self.pid = self.com.get_pid(self.primary_user_node, 'bin/gaussdb')
        self.log.info("进程号:" + self.pid)

    def test_main(self):
        try:
            text = "--step1:核对数据库状态;expect:Normal--"
            self.log.info(text)
            db_status = self.primary_sh.getDbClusterStatus("detail")
            self.log.info(db_status)
            self.assertTrue("Degraded" in db_status
                            or "Normal" in db_status, "执行失败" + text)

            text = "--step2:注入进程D 状态故障;expect:成功--"
            self.log.info(text)
            self.log.info("注入故障")
            inject_cmd = f'rProc_d (pid) values({self.pid})'
            self.log.info(inject_cmd)
            result = self.com.cfe_inject(self.primary_root_node,
                                         inject_cmd)
            self.log.info(result)
            self.assertIn("", result, "执行失败" + text)
            for i in range(6):
                time.sleep(10)
                result = self.com.cfe_query(self.primary_root_node,
                                            f"rProc_d where pid={self.pid}")
                self.log.info(result)
                if self.constant.NO_FILE_MSG in result:
                    break
            result = self.com.cfe_query(self.primary_root_node,
                                        f"rProc_d where pid={self.pid}")
            self.log.info(result)
            self.assertIn("State:\tD (disk sleep)", result, "执行失败" + text)

            text = "--step3:核对数据库状态;expect:Degrade--"
            self.log.info(text)
            db_status = self.primary_sh.getDbClusterStatus("detail")
            self.log.info(db_status)
            self.assertIn("S Standby Need repair", db_status, "执行失败" + text)
            self.assertIn("Degraded", db_status, "执行失败" + text)

        finally:
            text = "--step4:恢复环境;expect:成功"
            self.log.info(text)
            result = self.com.cfe_clean(self.primary_root_node,
                                        f"rProc_d where pid={self.pid}")
            self.log.info(result)
            self.assertEqual("", result, "执行失败" + text)

        result = self.primary_sh.executeGsctl("restart",
                                              "server started")
        self.log.info(result)
        self.assertTrue(result, "执行失败" + text)
        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status
                        or "Normal" in db_status, "执行失败" + text)
        self.assertNotIn("P Down", db_status, "执行失败" + text)

        text = "--step5:运行TPCC;expect:成功"
        self.log.info(text)
        result = self.com.startTPCC(self.primary_root_node, macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.constant.TPCC_SUCCESS_MSG, result, "执行失败" + text)

        text = "检查主备是否同步"
        self.log.info(text)
        time.sleep(10)
        self.log.info("获取节点数量")
        node_num = self.primary_sh.get_node_num()
        res = self.primary_sh.check_location_consistency("primary", node_num)
        self.assertTrue(res, "执行失败" + text)

        text = "--step6:检查数据一致性;expect:成功"
        self.log.info(text)
        nodes = (Node(self.nodes[0]), Node(self.nodes[1]),
                 Node(self.nodes[2]))
        flag = self.com.check_data_sample_by_all(r'\d', *nodes)
        self.assertTrue(flag, "执行失败" + text)
        table_dict = self.com.format_sql_result(
            self.primary_sh.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f"select count(*) from {name};"
            flag = self.com.check_data_sample_by_all(select_sql, *nodes)
            self.assertTrue(flag, "执行失败" + text)

    def tearDown(self):
        text = "--step7:恢复环境;expect:成功"
        self.log.info(text)
        result = self.com.cfe_clean(self.primary_root_node,
                                    f"rProc_d where pid={self.pid}")
        self.log.info(result)
        result = self.primary_sh.executeGsctl("restart",
                                              "server started")
        self.log.info(result)
        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status
                        or "Normal" in db_status, "执行失败" + text)
        self.log.info("Opengauss_Reliability_Process_Case010:执行完成")
